// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module vr_bypass
  (
   // ------------------------
   // Clock and Reset signals
   // ------------------------
   input        iClk, //clock for sequential logic, 2MHz 
   input        iRst_n, //reset signal, resets state machine to initial state
   
   // ----------------------------
   // inputs and outputs
   // ----------------------------
   
   //FORCE ON JUMPER
   input        iFM_FORCE_PWRON_LVC18, //VR FORCE ON, from DBG FPGA thru sGPIO
   
   
   //CPU PRSNT
   input        iFM_CPU0_SKTOCC_LVT3_PLD_N, //SKTOCC_N is used to protect system to not override sequence if CPU is installed
   input        iFM_CPU1_SKTOCC_LVT3_PLD_N, //SKTOCC_N is used to protect system to not override sequence if CPU is installed
   input        iFM_CPU0_INTR_PRSNT_N, //INTR_PRSNT_N is used to protect system to not override sequence if interposer is installed
   input        iFM_CPU1_INTR_PRSNT_N, //INTR_PRSNT_N is used to protect system to not override sequence if interposer is installed
   
   //system power rails PWRGD
   input        iPWRGD_P3V3_BP, //P3V3 MAIN
   input        iPWRGD_PS_PWROK_CPU_PLD_R_BP, //PS_PWROK
   
   input        iPWRGD_P1V0_AUX_BP,
   input        iPWRGD_P1V1_AUX_BP,
   
   //CPU0 rails PWRGD
   input        iPWRGD_PVCCFA_EHV_CPU0_BP, //PVCCFA_EHV
   input        iPWRGD_PVNN_MAIN_CPU0_BP, //PVNN
   input        iPWRGD_PVCCD0_HV_CPU0_BP, //PVCCD0
   input        iPWRGD_PVCCD1_HV_CPU0_BP, //PVCCD1
   input        iPWRGD_PVCCFA_EHV_FIVRA_CPU0_BP, //PVCCFA_EHV_FIVRA
   input        iPWRGD_PVCCINFAON_CPU0_BP, //PVCCINFAON
   input        iPWRGD_PVCCIN_CPU0_BP, //PVCCIN
   
   //CPU1 rails PWRGD
   input        iPWRGD_PVCCFA_EHV_CPU1_BP, //PVCCFA_EHV
   input        iPWRGD_PVNN_MAIN_CPU1_BP, //PVNN
   input        iPWRGD_PVCCD0_HV_CPU1_BP, //PVCCD0
   input        iPWRGD_PVCCD1_HV_CPU1_BP, //PVCCD1
   input        iPWRGD_PVPP_HBM_CPU1_BP, //PVPP_HBM
   input        iPWRGD_PVCCFA_EHV_FIVRA_CPU1_BP, //PVCCFA_EHV_FIVRA
   input        iPWRGD_PVCCINFAON_CPU1_BP, //PVCCINFAON
   input        iPWRGD_PVCCIN_CPU1_BP, //PVCCIN
   
   //LED display
   output [4:0] oLED_STATUS, //VR Bypass FSM status to be displayed on LEDs
   
   //System rails Power EN
   output reg   oFM_P3V3_EN_BP, //P3V3 MAIN Enable
   output reg   oFM_PS_EN_R_BP, //PSU Enable
   output reg   oFM_AUX_SW_EN_BP, //Switch power source from STBY to Main
   output reg   oFM_P5V_EN_BP, //Enable P5V main switch, need to be enabled before CPU main rail up
   output reg   oFM_P1V1_AUX_EN_BP, //Enable P1V1 AUX
   output reg   oFM_P1V0_AUX_EN_BP, //Enable P1V0 AUX
   
   output reg   oFM_P12V_DIMM_PCIE_SW_CPU0_EN_BP, //Enable PCIE/DIMM 12V Main power switch
   output reg   oFM_P12V_DIMM_PCIE_SW_CPU1_EN_BP, //Enable PCIE/DIMM 12V Main power switch
   
   //CPU0 rails enable
   output reg   oFM_PVCCFA_EHV_CPU0_R_EN_BP, //PVCCFA_EHV Enable
   output reg   oFM_PVNN_MAIN_CPU0_R_EN_BP, //PVNN Enable
   output reg   oFM_PVCCD_HV_CPU0_R_EN_BP, //PVCCD0 Enable

   output reg   oFM_PVCCFA_EHV_FIVRA_CPU0_R_EN_BP, //PVCCFA_EHV_FIVRA Enable
   output reg   oFM_PVCCINFAON_CPU0_R_EN_BP, //PVCCINFAON Enable
   output reg   oFM_PVCCIN_CPU0_R_EN_BP, //PVCCIN Enable
   
   //CPU0 rails enable
   output reg   oFM_PVCC3V3_AUX_CPU1_EN_BP, //PVCC3P3_AUX Enable, only valid for CPU1
   
   output reg   oFM_PVCCFA_EHV_CPU1_R_EN_BP, //PVCCFA_EHV Enable
   output reg   oFM_PVNN_MAIN_CPU1_R_EN_BP, //PVNN Enable
   output reg   oFM_PVCCD_HV_CPU1_R_EN_BP, //PVCCD0 Enable

   output reg   oFM_PVCCFA_EHV_FIVRA_CPU1_R_EN_BP, //PVCCFA_EHV_FIVRA Enable
   output reg   oFM_PVCCINFAON_CPU1_R_EN_BP, //PVCCINFAON Enable
   output reg   oFM_PVCCIN_CPU1_R_EN_BP //PVCCIN Enable
   
   
   );
   
   
   //////////////////////////////////////////////////////////////////////////////////
    // States for FSM
   //////////////////////////////////////////////////////////////////////////////////
   localparam     ST_INIT                     =     5'd0;
   
   localparam     ST_PVCCFA_EHV_CPU0          =     5'd1;
   localparam     ST_PVCCFA_EHV_CPU1          =     5'd2;
   
   localparam	  ST_P1V0_AUX_VR			  =     5'd3;
   localparam     ST_PVNN_AUX_CPU0           =     5'd4;
   localparam     ST_PVNN_AUX_CPU1           =     5'd5;
   
   localparam     ST_PSU1                     =     5'd6;
   localparam     ST_PSU2                     =     5'd7;
   localparam     ST_MAIN_PWR1                =     5'd8;
   localparam     ST_MAIN_PWR2                =     5'd9;
   
   localparam	  ST_P1V1_AUX_VR			  =     5'd10;
   localparam     ST_PVCCD_HV_CPU0           =      5'd11;
   localparam     ST_PVCCD_HV_CPU1           =      5'd12;   
   
   
   localparam     ST_PVCCFA_EHV_FIVRA_CPU0    =     5'd13;
   localparam     ST_PVCCFA_EHV_FIVRA_CPU1    =     5'd14;
   
   localparam     ST_PVCCINFAON_CPU0          =     5'd15;
   localparam     ST_PVCCINFAON_CPU1          =     5'd16;
   
   localparam     ST_PVCCIN_CPU0              =     5'd17;   
   localparam     ST_PVCCIN_CPU1              =     5'd18;
   
   localparam     ST_PLATFORM_ON              =     5'd19;
   
   
   
   
   //////////////////////////////////////////////////////////////////////////////////
   // Parameters
   //////////////////////////////////////////////////////////////////////////////////
   localparam  LOW =1'b0;
   localparam  HIGH=1'b1;
   
   //state
   reg [4:0]    state;
   
   reg          rTimerStart;                                                       //10ms timer start flag
   wire         wTimerDone;                                                        //10ms timer done flag
   
   wire         wVR_BYPASS_EN;                                                     //Enable VR BYPASS Mode
   
   //////////////////////////////////////////////////////////////////////////////////
   // Combinational logic
   //////////////////////////////////////////////////////////////////////////////////
   
   //VR_BYPASS_EN is asserted only when no CPU is installed and only i mode is valid
   assign      wVR_BYPASS_EN    =   iFM_FORCE_PWRON_LVC18;
   
   //output assignment
   assign      oLED_STATUS      =   state;
   
   //////////////////////////////////////////////////////////////////////////////////
   // VR_BYPASS FSM logic
   //////////////////////////////////////////////////////////////////////////////////
   
   
   always @(posedge iClk or negedge iRst_n)  begin
	  if(!iRst_n)                            begin                                 //reset state
		 state                             <=   ST_INIT;
         oFM_P5V_EN_BP                     <=   LOW;
         
         oFM_PVCC3V3_AUX_CPU1_EN_BP        <=   LOW;
         
         oFM_PVCCFA_EHV_CPU1_R_EN_BP       <=   LOW;
         oFM_PVCCFA_EHV_CPU0_R_EN_BP       <=   LOW;
         oFM_P1V0_AUX_EN_BP			       <=   LOW;                 
         oFM_PVNN_MAIN_CPU0_R_EN_BP        <=   LOW;
		 oFM_PVNN_MAIN_CPU1_R_EN_BP        <=   LOW;
         
         oFM_PS_EN_R_BP                    <=   LOW;
         oFM_AUX_SW_EN_BP                  <=   LOW;
         oFM_P3V3_EN_BP                    <=   LOW;
         
         
         oFM_P12V_DIMM_PCIE_SW_CPU0_EN_BP  <=   LOW;
		 oFM_P12V_DIMM_PCIE_SW_CPU1_EN_BP  <=   LOW;
         
		 oFM_P1V1_AUX_EN_BP                <=   LOW;
         oFM_PVCCD_HV_CPU0_R_EN_BP         <=   LOW;
		 oFM_PVCCD_HV_CPU1_R_EN_BP         <=   LOW;
         
		 oFM_PVCCFA_EHV_FIVRA_CPU0_R_EN_BP <=   LOW;
         oFM_PVCCFA_EHV_FIVRA_CPU1_R_EN_BP <=   LOW;
         
		 oFM_PVCCINFAON_CPU0_R_EN_BP       <=   LOW;
         oFM_PVCCINFAON_CPU1_R_EN_BP       <=   LOW;
         
		 oFM_PVCCIN_CPU0_R_EN_BP           <=   LOW;
         oFM_PVCCIN_CPU1_R_EN_BP           <=   LOW;
         
		 rTimerStart                       <=   LOW;
         
		 
	  end
	  else begin
		 if(wVR_BYPASS_EN) begin                                                   //if it's enabled
			case(state)
			  ST_INIT: begin
                 oFM_P5V_EN_BP                     <=   LOW;                      //removing VRs WA
                 oFM_PVCC3V3_AUX_CPU1_EN_BP        <=   HIGH;
                 rTimerStart                       <=   HIGH;
                 if(wTimerDone) begin
				    state                          <=   ST_PVCCFA_EHV_CPU0 ;       //move to next state
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
			  end
              
              ST_PVCCFA_EHV_CPU0: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCFA_EHV_CPU0_R_EN_BP       <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCFA_EHV_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
			  end // case: ST_PVCCFA_EHV_CPU0
              
              ST_PVCCFA_EHV_CPU1: begin
                 rTimerStart                       <=   HIGH;
                 oFM_PVCCFA_EHV_CPU1_R_EN_BP       <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_P1V0_AUX_VR;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
			  end // case: ST_PVCCFA_EHV_CPU1
              
              ST_P1V0_AUX_VR: begin
                 oFM_P1V0_AUX_EN_BP                <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVNN_AUX_CPU0;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_P1V0_AUX_VR
              
              ST_PVNN_AUX_CPU0: begin

                 rTimerStart                       <=   HIGH;
                 oFM_PVNN_MAIN_CPU0_R_EN_BP        <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVNN_AUX_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
			  end
              
              ST_PVNN_AUX_CPU1: begin
                 rTimerStart                       <=   HIGH;
                 oFM_PVNN_MAIN_CPU1_R_EN_BP        <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PSU1;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
			  end // case: ST_PVNN_AUX_CPU1
              
              ST_PSU1: begin
                 rTimerStart                       <=   HIGH;
                 oFM_PS_EN_R_BP                    <=   HIGH;
                 if(wTimerDone) begin
                    state                       <=   ST_PSU2;
                    rTimerStart                 <= LOW;                       
                 end
              end
              
              ST_PSU2: begin
                 rTimerStart                       <=   HIGH;
                 oFM_AUX_SW_EN_BP                  <=   HIGH;
                 if(wTimerDone) begin
                    state                          <=   ST_MAIN_PWR1;
                    rTimerStart                    <=   LOW;
                 end
              end
              
              ST_MAIN_PWR1: begin
                 rTimerStart                       <=   HIGH;
                 oFM_P5V_EN_BP                     <=   HIGH;
                 if(wTimerDone) begin
                    state                          <=   ST_MAIN_PWR2;
                    rTimerStart                    <=   LOW;
                 end
              end
              
              ST_MAIN_PWR2: begin
                 rTimerStart                       <=   HIGH;
                 oFM_P3V3_EN_BP                    <=   HIGH;
                 if(wTimerDone) begin
                    rTimerStart <= LOW;
                    state                          <=   ST_P1V1_AUX_VR;   
                    rTimerStart                    <=   LOW;
                 end
              end // case: ST_MAIN_PWR2             
              
              ST_P1V1_AUX_VR: begin
                 oFM_P12V_DIMM_PCIE_SW_CPU0_EN_BP  <=   HIGH;
                 oFM_P12V_DIMM_PCIE_SW_CPU1_EN_BP  <=   HIGH;
                 rTimerStart                       <=   HIGH;
                 oFM_P1V1_AUX_EN_BP                <=   HIGH;                      //Enable VR
				 if( wTimerDone) begin
				    state                          <=   ST_PVCCD_HV_CPU0;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
              end
              
              ST_PVCCD_HV_CPU0: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCD_HV_CPU0_R_EN_BP         <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCD_HV_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
              end // case: ST_PVCCD_HV_CPU0
              
              ST_PVCCD_HV_CPU1: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCD_HV_CPU1_R_EN_BP         <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCFA_EHV_FIVRA_CPU0;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
              end // case: ST_PVCCD_HV_CPU1              
              
              ST_PVCCFA_EHV_FIVRA_CPU0: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCFA_EHV_FIVRA_CPU0_R_EN_BP <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCFA_EHV_FIVRA_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_PVCCFA_EHV_FIVRA_CPU0
              
              ST_PVCCFA_EHV_FIVRA_CPU1: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCFA_EHV_FIVRA_CPU1_R_EN_BP <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCINFAON_CPU0;
				    rTimerStart                    <=   LOW;                         //clear timer
				 end
              end // case: ST_PVCCFA_EHV_FIVRA_CPU1              
              
              ST_PVCCINFAON_CPU0: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCINFAON_CPU0_R_EN_BP       <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCINFAON_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_PVCCINFAON_CPU0
              
              ST_PVCCINFAON_CPU1: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCINFAON_CPU1_R_EN_BP       <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCIN_CPU0;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_PVCCINFAON_CPU1
              
              ST_PVCCIN_CPU0: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCIN_CPU0_R_EN_BP           <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PVCCIN_CPU1;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_PVCCIN_CPU0
              
              ST_PVCCIN_CPU1: begin
                 rTimerStart                       <=   HIGH;                      //Start timer
                 oFM_PVCCIN_CPU1_R_EN_BP           <=   HIGH;                      //Enable VR
				 if(wTimerDone) begin
				    state                          <=   ST_PLATFORM_ON;
				    rTimerStart                    <=   LOW;                         //clear timer
                 end
              end // case: ST_PVCCIN_CPU1
              
			  ST_PLATFORM_ON:           begin
				 state                                <=   ST_PLATFORM_ON;              //The only way out of ST_PLATFORM_ON is AC cycle
			  end
			  
			  default:                  begin
				 state                               <=   ST_INIT;
			  end	
			  
			endcase // case (state)
            
			
		 end // if (wVR_BYPASS_EN)
         
         
		 else begin
			state                               <=   ST_INIT;
         	oFM_P5V_EN_BP                       <=   LOW;
			
			//system rails enable
         	oFM_P3V3_EN_BP                      <=   LOW;
         	oFM_PS_EN_R_BP                      <=   LOW;
         	oFM_AUX_SW_EN_BP                    <=   LOW;
         	oFM_P12V_DIMM_PCIE_SW_CPU0_EN_BP    <=   LOW;
         	oFM_P12V_DIMM_PCIE_SW_CPU1_EN_BP    <=   LOW;
	        
         	//CPU0 rails enable
         	oFM_PVCCFA_EHV_CPU0_R_EN_BP         <=   LOW;
         	oFM_PVNN_MAIN_CPU0_R_EN_BP          <=   LOW;
         	oFM_PVCCD_HV_CPU0_R_EN_BP           <=   LOW;
         	oFM_PVCCFA_EHV_FIVRA_CPU0_R_EN_BP   <=   LOW;
         	oFM_PVCCINFAON_CPU0_R_EN_BP         <=   LOW;
         	oFM_PVCCIN_CPU0_R_EN_BP             <=   LOW;
	        
         	//CPU0 rails enable
            oFM_PVCC3V3_AUX_CPU1_EN_BP          <=   LOW;
	        
         	oFM_PVCCFA_EHV_CPU1_R_EN_BP         <=   LOW;
         	oFM_PVNN_MAIN_CPU1_R_EN_BP          <=   LOW;              
         	oFM_PVCCD_HV_CPU1_R_EN_BP           <=   LOW;              
         	oFM_PVCCFA_EHV_FIVRA_CPU1_R_EN_BP   <=   LOW;     
         	oFM_PVCCINFAON_CPU1_R_EN_BP         <=   LOW;           
         	oFM_PVCCIN_CPU1_R_EN_BP             <=   LOW;
			
			rTimerStart                         <=   LOW;
		 end //if(!wVR_BYPASS_EN)
	  end //if(!iRst_n)
	  
   end 
   
   
   //////////////////////////////////////////////////////////////////////////////////
   // Instance
   //////////////////////////////////////////////////////////////////////////////////
   
   //5-sec Timer, started when rTimerStart is asserted
   delay #(.COUNT(10000000)) 
   Timer10ms(
             .iClk(iClk),
             .iRst(iRst_n),
             .iStart(rTimerStart),
             .iClrCnt(1'b0),
             .oDone(wTimerDone)
             );
   
   
   
endmodule
